﻿using System.Security.Cryptography;
using System.Text;

namespace Common.Class
{
    public class EncryptHelper
    {
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="plainText">需要加密的字符串</param>
        /// <returns></returns>
        public static string EncryptString_MD5(string plainText)
        {
            using (MD5 md5Hash = MD5.Create())
            {
                byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(plainText));
                StringBuilder sBuilder = new StringBuilder();
                for (int i = 0; i < data.Length; i++)
                {
                    sBuilder.Append(data[i].ToString("x2"));
                }
                return sBuilder.ToString();
            }
        }

        #region AES-256对称加密

        /// <summary>
        /// Aes加密，自动产生iv
        /// </summary>
        /// <param name="plainText">待加密字符串</param>
        /// <param name="key">密钥，最多32个字符</param>
        /// <returns></returns>
        public static string EncryptString_Aes(string plainText, string key)
        {
            if (string.IsNullOrWhiteSpace(plainText))
            {
                return "";
            }

            if (key.Length > 32)
            {
                key = key.Substring(0, 32);
            }

            if (key.Length < 32)
            {
                key = key.PadLeft(32, '0');
            }

            byte[] keyByte = Encoding.UTF8.GetBytes(key); // 256位密钥
            byte[] iv = new byte[16];// 128位IV

            using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
            {
                //产生16个随机数
                rng.GetBytes(iv);
            }

            string siv = Convert.ToBase64String(iv).Substring(0, 22);


            string es = EncryptString_Aes(plainText, keyByte, iv);

            return siv + es;
        }
        /// <summary>
        /// Aes加密，自动产生iv
        /// </summary>
        /// <param name="plainText">待加密字符串</param>
        /// <param name="keyByte">密钥</param>
        /// <returns></returns>
        public static string EncryptString_Aes(string plainText, byte[] keyByte)
        {
            if (string.IsNullOrWhiteSpace(plainText))
            {
                return "";
            } 
             
            byte[] iv = new byte[16];// 128位IV

            using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
            {
                //产生16个随机数
                rng.GetBytes(iv);
            }

            string siv = Convert.ToBase64String(iv).Substring(0, 22);


            string es = EncryptString_Aes(plainText, keyByte, iv);

            return siv + es;
        }

        /// <summary>
        /// Aes加密
        /// </summary>
        /// <param name="plainText">待加密的字符串</param>
        /// <param name="Key">密钥</param>
        /// <param name="IV">初始化向量 通常是16字节（128位）</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static string EncryptString_Aes(string plainText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");
            byte[] encrypted;

            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;
                aesAlg.Mode = CipherMode.CBC;
                aesAlg.Padding = PaddingMode.PKCS7;

                // Create an encryptor to perform the stream transform.
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }

            // Return the encrypted bytes from the memory stream.
            return Convert.ToBase64String(encrypted);
        }

        /// <summary>
        /// Aes解密，自动产生iv
        /// </summary>
        /// <param name="cipherText">待解密字符串</param>
        /// <param name="Key">密钥</param>
        /// <returns></returns>
        public static string DecryptString_Aes(string cipherText, string Key)
        {
            if (string.IsNullOrWhiteSpace(cipherText))
            {
                return "";
            }

            if (Key.Length > 32)
            {
                Key = Key.Substring(0, 32);
            }

            if (Key.Length < 32)
            {
                Key = Key.PadLeft(32, '0');
            }

            byte[] key = Encoding.UTF8.GetBytes(Key);
            string siv = cipherText.Substring(0, 22) + "==";
            byte[] iv = Convert.FromBase64String(siv);

            return DecryptString_Aes(cipherText.Substring(22), key, iv);

        }


        /// <summary>
        /// Aes解密，自动产生iv
        /// </summary>
        /// <param name="cipherText">待解密字符串</param>
        /// <param name="Key">密钥</param>
        /// <returns></returns>
        public static string DecryptString_Aes(string cipherText, byte[] keyByte)
        {
            if (string.IsNullOrWhiteSpace(cipherText))
            {
                return "";
            }
             
            string siv = cipherText.Substring(0, 22) + "==";
            byte[] iv = Convert.FromBase64String(siv);

            return DecryptString_Aes(cipherText.Substring(22), keyByte, iv);

        }

        /// <summary>
        /// Aes解密
        /// </summary>
        /// <param name="cipherText">待解密的字符串</param>
        /// <param name="Key">密钥</param>
        /// <param name="IV">初始化向量 通常是16字节（128位）</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static string DecryptString_Aes(string cipherText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;
                aesAlg.Mode = CipherMode.CBC;
                aesAlg.Padding = PaddingMode.PKCS7;

                // Create a decryptor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            return plaintext;
        }

        #endregion

        #region RSA非对称加密

        /// <summary>
        /// 获取RSA加密公钥和私钥
        /// </summary>
        /// <param name="publicKey">返回公钥</param>
        /// <param name="privateKey">返回私钥</param>
        public static void GenerateRSAKeyPair_RSA(out string publicKey, out string privateKey)
        {
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
            {
                publicKey = rsa.ToXmlString(false);
                privateKey = rsa.ToXmlString(true);
            }
        }

        /// <summary>
        /// RSA加密数据
        /// </summary>
        /// <param name="data">数据字符串</param>
        /// <param name="publicKey">公钥</param>
        /// <returns></returns>
        public static string EncryptString_RSA(string plainText, string publicKey)
        {
            byte[] dataToEncrypt = Encoding.UTF8.GetBytes(plainText);
            using (var rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(publicKey);
                string _rs = Convert.ToBase64String(rsa.Encrypt(dataToEncrypt, false));
                return _rs;
            }
        }

        /// <summary>
        /// RSA解密数据
        /// </summary>
        /// <param name="data">数据字符串</param>
        /// <param name="privateKey">私钥</param>
        /// <returns></returns>
        public static string DecryptString_RSA(string cipherText, string privateKey)
        {
            byte[] encryptedData = Convert.FromBase64String(cipherText);
            using (var rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(privateKey);
                string _rs = System.Text.Encoding.UTF8.GetString(rsa.Decrypt(encryptedData, false));
                return _rs;
            }
        }

        #endregion


    }
}
